本文介绍了Gforce for Perforce用户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我一直在使用Perforce多年。我想切换到使用git作为我的个人代码,但是我所见过的所有git教程都假设你是一个完整的源代码控制n00b(这使得它们令人难以置信的乏味)或者你习惯于svn(我不是)。 我知道p4,我也理解分布式源代码控制系统背后的想法(所以我不需要销售点, 谢谢)。我想要的是从p4命令到等价的git命令的转换表,以及不能没有p4等效命令的命令。 因为我怀疑每个p4用户使用p4的不同子集,下面是我经常在p4中做的一些事情,我希望能够在git中做到这一点,从我看过的文档中并不明显: 在单个客户端中创建多个挂起的更改列表。 ( p4更改) 编辑暂挂更改列表。 ( p4 change ) 查看我所有待处理的更改列表( p4 changes -s pending ) 我的客户端中所有已更改文件的列表( p4已打开)或待处理更改列表( p4 describe ) 查看暂挂更改列表的差异(我使用包装脚本来执行此操作,它使用 p4 diff 和 p4描述) 查看给定文件的哪些提交的更改列表, ( p4 annotate ) 对于给定文件,请参阅影响文件的变更列表的说明列表( p4 log ) 提交待处理的更改列表( p4 submit -c li> 中止待处理的更改列表( p4还原) 其中很多都围绕变更名单。 changelist是p4的术语。什么是git等效项? 听起来分支可能是git用户用来代替p4调用变更列表的地方。有点混乱,因为p4也有一些叫做分支的东西,尽管它们似乎只是模糊的相关概念。 (尽管我一直认为p4的分支概念很奇怪,但它与分支的经典RCS概念再次不同。) 无论如何...我是不确定如何通过git的分支来完成我通常在p4 changelists中所做的工作。在p4中,我可以这样做: $ p4编辑a.txt $ p4更改a.txt 更改12345创建。 此时我有一个包含a.txt的changlist。我可以编辑描述并继续工作,而无需提交更改列表。另外,如果事实证明我需要对其他一些文件进行一些修改,比如说在代码的其他一层中说错误修正,我可以在同一个客户端上做到这一点: $ p4编辑z.txt $ p4更改z.txt 更改12346创建。 现在我在同一个客户端中有两个单独的更改列表。我可以同时处理这些问题,而且我不需要做任何事情来切换它们。当提交时,我可以分别提交它们: $ p4 submit -c 12346#这会将更改提交给z.txt $ p4 submit -c 12345#这会将变更提交给a.txt git add 与当前分支关联。据我所知,当我 git commit 它将提交所有文件,我 git add -ed no问题:当时我在哪个分支: $ git init / home / laurence中初始化的空Git存储库/git-playground/.git/ $ ls a.txt w.txt z.txt $ git add -A。 $ git commit 初始提交。 3个文件已更改,3个插入(+),0个删除( - )创建模式100644 a.txt 创建模式100644 w.txt 创建模式100644 z.txt $ vi a.txt z.txt 2个文件编辑 $ git status #分支主#已更改但未更新:#(使用git add< file> ...来更新将要提交的内容)#(使用git checkout - < file> ...放弃工作目录中的更改) ##修改:a.txt #修改:z.txt #没有更改添加到提交中(使用git add和/或git commit -a ) $ git branch aardvark $ git checkout aardvark M a.txt M z.txt 转换到分支'aardvark' $ git add a.txt $ git checkout master M a.txt M z.txt 转换到分支'master' $ git分支zebra $ git checkout zebra M a.txt M z.txt 转换到分支'zebra' $ git add z.txt $ git status #分支斑马#Chang es被提交:#(使用git reset HEAD< file> ...停用)##修改:a.txt #修改:z .txt # $ git checkout aardvark M a.txt M z.txt 转换到分支'aardvark' $ git status #在分支aardvark上#要提交的更改:#(使用git reset HEAD< file> ...来暂停)##modified: a.txt #modified:z.txt 在这个例子中,土豚和斑马分支似乎包含完全相同的一组更改,并且基于 git status 的输出,似乎在两者中执行提交都会产生相同的效果。我做错了什么?解决方案我没有使用perforce太多,所以这可能不完全是1:1的翻译。然后,像git和mercurial这样的分布式源代码控制系统又有不同的工作流程,所以实际上没有(也不应该)有1:1的翻译。无论如何,这里有: 创建多个挂起的更改列表 - >使用分支。在git分支中轻巧快速,创建时间不到一秒,通常不到两秒即可合并。 git分支新分支名称 git checkout new-分行名称 或者在一行内完成: git checkout -b新分支名称 查看所有待处理的更改列表 - >因为多个待处理的更改列表的等价物是多个分支,只需查看分支: git branch 如果您还想查看远程分支: git branch -a 在合并成功后立即删除一个分支被认为是一种好的做法,所以你不必跟踪哪个分支有待合并和哪些分支已经合并。 列出所有更改的文件 - >对于特定分支中的单个未决changelist,git具有索引或缓存的概念。为了提交更改,您必须先将文件添加到此索引。这使您可以手动选择哪组文件表示单个更改或忽略不相关的文件。要查看添加哪些文件的状态,或者不查看此索引,请执行以下操作: git status code> 查看待处理更改列表的差异 - >这有两个部分。首先看到工作目录和索引之间的差异: git diff 但是如果你想知道你现在输入的内容和最后一次提交之间的差异,那么你实际上是要求在工作目录+ index和HEAD: pre $ g $ diff $ HEAD $ / code> 对于给定的文件, git blame文件名 或甚至更好,如果您处于窗口环境中: git gui blame文件名 Git gui解析文件需要更长的时间(它是用tcl而不是C编写的),但它具有许多简洁的功能,包括通过单击提交ID来时间旅行回到过去的能力。我只希望他们能够实现一个功能来将时间旅行到未来,以便我可以找出如何最终解决给定的错误; - ) >对于给定的文件,查看影响文件的更改列表描述 - >也很容易: git log文件名 但git log是一个比这更强大的工具。实际上,我的大多数个人脚本都是通过git日志来读取存储库。阅读手册页。 git commit 请参阅我回答以前的问题,看看我的典型git工作流程:学习混帐。需要知道我是否在正确的轨道上 如果您按照我列出的工作流程,那么您会发现像gitk这样的工具会更有价值,它允许你清楚地看到一组变化。 附加答案: Git非常灵活,可以通过多种方式来完成您所描述的内容。要记住的是总是为你正在工作的每个功能启动一个新的分支。这意味着主分支没有被触及,因此您可以随时回到它来修复错误。在git中工作应该几乎总是从以下开始: git checkout -b新特性-a 现在您可以编辑文件a.txt。同时使用另一个功能: git checkout master git checkout -b new-feature-z 现在您可以编辑文件z.txt。切换回a.txt: git checkout新特性-a 但是等一下,新特性-z有变化,git不会让你切换分支。在这一点上,你有两个选择。第一个是最简单的,对当前分支提交所有更改: git add。 git commit git checkout new-feature -a 这就是我'推荐。但如果你还没有准备好提交代码,你可以暂时隐藏它: git stash code> 现在您可以切换到分支新功能-a。回到你正在处理的代码中,只需弹出存储: git checkout new-feature-z git stash pop 完成全部操作后,将所有更改合并到master: git merge --no-ff new-feature -a git merge --no-ff new-feature-z 由于合并过程非常快速和简单(容易,因为冲突很少,解决冲突的时候,一旦发生,不会太难)我们在git中使用分支来处理所有事情。 下面是git中常用分支的另一个例子,在其他源代码控制工具中没有看到(除了mercurial ): 需要不断更改配置文件以反映您的开发环境?然后使用分支: git checkout -b dev-config c> git add。 git commit 现在每个新分支都可以从dev-config分支开始,而不是主分支: git checkout dev-config git checkout -b新功能分支 一旦完成,使用交互式rebase从新特性分支中删除dev-config中的编辑: git rebase -i master git checkout master git merge --no-ff new-feature-branch #因为master已经改变了,所以重新设置dev-config是个好主意: git checkout dev-config git rebase master 值得注意的是,当所有更改发生在同一个文件中时,使用 git rebase -i 。 Git记住了变化,而不是文件内容*。 *注意:实际上,技术上不是完全正确的,而是作为用户的感觉 / p> 更多附加答案: 看起来你想要有两个分支同时存在,所以你可以测试组合代码的工作方式。那么,这是说明分支机构的强大功能和灵活性的好方法。 首先,关于便宜分支和可修改历史对您工作流程的影响。当我使用CVS和SVN时,我总是有点不情愿承诺。这是因为提交不稳定的代码将不可避免地破坏其他人的工作代码。但用git我失去了这种恐惧。这是因为在git中,其他人在将它们合并到主人之前不会获得我的更改。所以现在我发现自己每写5行代码。你不需要完美的先见之明。你只需要改变你的想法:commit-to-branch == add-to-changeset,merge-to-master == commit-changeset。 以示例。这就是我将如何去做的。假设你有一个分支 new-feature-z 并且你想用 new-feature-a 来测试它。我只是创建一个新的分支来测试它: #假设我们目前处于分支中new-feature-z #关闭此分支以测试 git checkout -b功能-z和功能-a #现在暂时合并新功能-a git merge --no-ff new -feature-a 现在您可以测试了。如果您需要修改某些内容以使feature-z能够与feature-a配合使用,那么请执行此操作。如果是这样,您可以将更改合并回相关分支。使用 git rebase -i 从合并中删除不相关的更改。另外,您还可以使用git rebase暂时将新功能-z的基础改为指向新功能-a: #假设我们目前处于分支new-feature-z git rebase new-feature-a 现在分支历史记录是因此新功能-Z将基于新功能-a而不是主功能。现在你可以测试。在此分支中提交的任何更改将属于分支new-feature-z。如果你需要修改新功能,只需切换回来,并重新获得新的更改: git checkout新特性a #编辑代码,添加,提交等。 git checkout新特性z git rebase新特性a #now新特性-z将包含来自新功能-a的新更改 完成后,只需重新归还要掌握从新功能-a中删除更改: #假设我们当前处于分支中new-feature-z git rebase master 不要害怕开始一个新的分支。不要害怕开始一次性分支。不要害怕扔掉树枝。而且,因为合并==提交和提交==添加到变更集不要经常犯。请记住,提交是一个开发人员的最终撤消工具。 哦,另外一件事,在git中删除的分支仍然存在于你的仓库中。所以,如果你不小心删除了一些你以后认识到的东西,那么你总是可以通过搜索历史来找回它。所以不要害怕扔掉分支。 I've been using Perforce for a number of years. I'd like to switch to using git for my personal code, but all of the git tutorials that I've seen either assume that you'e a complete source control n00b (which makes them incredibly tedious) or that you're used to svn (which I'm not).I know p4, and I also understand the idea behind a distributed source control system (so I don't need a sales pitch, thanks). What I'd like is a translation table from p4 command to equivalent git commands, as well as the "can't live without" commands that have no p4 equivalent.Since I suspect every p4 user uses a different subset of p4, here are some of the things I regularly do in p4 that I'd like to be able to do in git that aren't immediately obvious from the docs I've looked at:create multiple pending changelists in a single client. (p4 change)edit a pending changelist. (also p4 change)see a list of all of my pending changelists (p4 changes -s pending)list of all of the changed files in my client (p4 opened) or in a pending changelist (p4 describe)see a diff of a pending changelist (I use a wrapper script for this which uses p4 diff and p4 describe)for a given file, see which submitted changelists affected which lines (p4 annotate)for a given file, see a list of the descriptions of the changelists that affected the file (p4 log)submit a pending changelist (p4 submit -c)abort a pending changelist (p4 revert)A lot of these revolve around "changelists". "changelist" is p4 terminology. What's the git equivalent term?It sounds like branches might be what git users use in place of what p4 calls changelists. A bit confusing, since p4 also has something called a branch though they seem to be only vaguely related concepts. (Though I always thought p4's concept of a branch was pretty weird it is different yet again from the classic RCS concept of a branch.)Anyway... I'm not sure how to accomplish what I normally do in p4 changelists with git's branches. In p4 I can do something like this:$ p4 edit a.txt$ p4 change a.txtChange 12345 created.At this point I have a changlist that contains a.txt. I can edit the description and continue working without submitting the changelist. Also, if it turns out that I need to make some changes to some other files, like say a bugfix in some other layer of the code, I can do that in the same client:$ p4 edit z.txt$ p4 change z.txtChange 12346 created.Now I have two separate changelists in the same client. I can work on these concurrently, and I don't need to do anything to "switch between" them. When it comes time to commit, I can submit them separately:$ p4 submit -c 12346 # this will submit the changes to z.txt$ p4 submit -c 12345 # this will submit the changes to a.txtI can't figure out how to replicate this in git. From my experiments, it doesn't appear that git add is associated with the current branch. As far as I can tell, when I git commit it's going to commit all files that I git add-ed no matter what branch I was in at the time:$ git initInitialized empty Git repository in /home/laurence/git-playground/.git/$ lsa.txt w.txt z.txt$ git add -A .$ git commit Initial commit. 3 files changed, 3 insertions(+), 0 deletions(-) create mode 100644 a.txt create mode 100644 w.txt create mode 100644 z.txt$ vi a.txt z.txt 2 files to edit$ git status# On branch master# Changed but not updated:# (use "git add <file>..." to update what will be committed)# (use "git checkout -- <file>..." to discard changes in working directory)## modified: a.txt# modified: z.txt#no changes added to commit (use "git add" and/or "git commit -a")$ git branch aardvark$ git checkout aardvarkM a.txtM z.txtSwitched to branch 'aardvark'$ git add a.txt $ git checkout masterM a.txtM z.txtSwitched to branch 'master'$ git branch zebra$ git checkout zebraM a.txtM z.txtSwitched to branch 'zebra'$ git add z.txt $ git status# On branch zebra# Changes to be committed:# (use "git reset HEAD <file>..." to unstage)## modified: a.txt# modified: z.txt#$ git checkout aardvarkM a.txtM z.txtSwitched to branch 'aardvark'$ git status# On branch aardvark# Changes to be committed:# (use "git reset HEAD <file>..." to unstage)## modified: a.txt# modified: z.txtIn this example, the aardvark and zebra branches seem to contain exactly the same set of changes, and based on the output of git status it appears that doing a commit in either will have the same effect. Am I doing something wrong? 解决方案 I haven't used perforce much so this may not be exactly be a 1:1 translation. Then again distributed source control systems like git and mercurial have a different workflow anyway so there really isn't (and there shouldn't) be a 1:1 translation. Anyway, here goes:Create multiple pending changelists -> Use branches instead. In git branches are light and quick, takes less than a second to create and typically less than two seconds to merge. Don't be afraid of branching and rebase often.git branch new-branch-namegit checkout new-branch-nameOr do it all in one line:git checkout -b new-branch-nameSee a list of all pending changelists -> Since the equivalent of multiple pending changelist is multiple branches just view the branches:git branchIf you want to view remote branches as well:git branch -aIt is considered good practice to immediately delete a branch after a successful merge so you don't have to keep track of which branch are pending to be merged and which have already been merged.List all changed files -> For a single pending "changelist" in a specific branch git has a concept of the index or cache. In order to commit a change you must first add files to this index. This allows you to manually select which group of files represent a single change or to ignore irrelevant files. To see the status of which files are added, or not to this index just do:git statusSee a diff of a pending changelist -> There are two parts to this. First to see a diff between the working directory and the index:git diffBut if you want to know the diff between what you're typing now and the last commit then you are really asking for a diff between the working directory+index and the HEAD:git diff HEADFor a given file, see which submitted changelists affected which lines -> This is easy:git blame filenameor even better, if you are in a windowing environment:git gui blame filenameGit gui takes longer to parse the file (it was written in tcl instead of C) but it has lots of neat features including the ability to "time travel" back into the past by clicking on a commit ID. I only wish they'd implement a feature to "time travel" to the future so I can find out how a given bug will finally be resolved ;-)For a given file, see a list of the descriptions of the changelists that affected the file -> also easy:git log filenameBut git log is a much more powerful tool than just this. In fact most of my personal scripts piggyback off-of git log to read the repository. Read the man page.Submit a pending changelist -> Also easy:git commitSee my answer to a previous question to see my typical git workflow: Learning Git. Need to know if I am on the right trackIf you follow the workflow I outlined then you'll find tools like gitk to be much more valuable since it allows you to clearly see groups of changes.Additional answer:Git is very flexible and there are several ways to do what you describe. The thing to remember is to always start a new branch for each feature you're working on. This means the master branch isn't touched so you can always go back to it to do bug fixes. Working in git one should almost always start with:git checkout -b new-feature-aNow you can edit file a.txt. To work concurrently on another feature do:git checkout mastergit checkout -b new-feature-zNow you can edit file z.txt. To switch back to a.txt:git checkout new-feature-aBut wait, there are changes to new-feature-z and git won't let you switch branches. At this point you have two choices. The first is the simplest, commit all changes to the current branch:git add .git commitgit checkout new-feature-aThis is what I'd recommend. But if you are really not ready to commit the code, you can temporarily stash it:git stashNow you can switch to branch new-feature-a. To go back to the code you were working on just pop the stash:git checkout new-feature-zgit stash popWhen all is done merge back all changes to master:git merge --no-ff new-feature-agit merge --no-ff new-feature-zBecause merges are so quick and easy (easy because conflicts are so rare and conflict resolution, when one does happen, not too hard) we use branches in git for everything.Here's another example of a common use of branches in git that you don't see in other source control tools (except perhaps mercurial):Need to keep changing your config files to reflect your dev environment? Then use a branch:git checkout -b dev-configNow edit your config files in your favourite editor then commit changes:git add .git commitNow every new branch can start from the dev-config branch instead of master:git checkout dev-configgit checkout -b new-feature-branchOnce you're done remove the edits in dev-config from new-feature-branch using interactive rebase:git rebase -i masterDelete the commits you don't want then save. Now you have a clean branch without custom config edits. Time to merge back to master:git checkout mastergit merge --no-ff new-feature-branch# because master have changed, it's a good idea to rebase dev-config:git checkout dev-configgit rebase masterIt should be noted that removing edits with git rebase -i even works when all changes happen in the same file. Git remembers changes, not file content*.*note: actually, technically not entirely true but as a user that's what it feels likeMore additional answer:So, from you comments it looks like you want to have two branches to exist simultaneously so you can test how the combined code works. Well, this is a good way to illustrate the power and flexibility of branches.First, a word on the implication of cheap branching and modifiable history on your workflow. When I was using CVS and SVN I was always a bit reluctant to commit. That's because committing unstable code would inevitably f**k up other people's working code. But with git I lost that fear. That's because in git other people won't get my changes until I merge them to master. So now I find myself committing code every 5 lines I write. You don't need perfect foresight to commit. You just need to change your mindset: commit-to-branch==add-to-changeset, merge-to-master==commit-changeset.So, back to examples. Here's how I would do it. Say you have a branch new-feature-z and you want to test it with new-feature-a. I would just create a new branch to test it:# assume we are currently in branch new-feature-z# branch off this branch for testinggit checkout -b feature-z-and-feature-a# now temporarily merge new-feature-agit merge --no-ff new-feature-aNow you can test. If you need to modify something to make feature-z work with feature-a then do so. If so you can merge back the changes to the relevant branch. Use git rebase -i to remove irrelevant changes from the merge.Alternatively, you can also use git rebase to temporarily change the base of new-feature-z to point to new-feature-a:# assume we are currently in branch new-feature-zgit rebase new-feature-aNow the branch history is modified so that new-feature-z will be based off new-feature-a instead of master. Now you can test. Any changes committed in this branch will belong to the branch new-feature-z. If you need to modify new-feature-a just switch back to it and the rebase to get the new changes:git checkout new-feature-a# edit code, add, commit etc..git checkout new-feature-zgit rebase new-feature-a# now new-feature-z will contain new changes from new-feature-aWhen you're done, simply rebase back to master to remove changes from new-feature-a:# assume we are currently in branch new-feature-zgit rebase masterDon't be afraid to start a new branch. Don't be afraid to start a throwaway branch. Don't be afraid to throw away branches. And since merge==submit and commit==add-to-changeset don't be afraid to commit often. Remember, commit is a developer's ultimate undo tool.Oh, and another thing, in git deleted branches still exist in your repository. So if you've accidentally deleted something that you later realise is useful after all you can always get it back by searching the history. So don't be afraid to throw away branches. 这篇关于Gforce for Perforce用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
10-21 11:28