top | item 40207286

(no title)

datascienced | 1 year ago

I wont claim to understand C and the reason why <> is better than “”. I assume it is.

But the fact that a merge can have arbitrary changes in it always bothers me!

This is a case for rebase over merge if there are conflicts.

You could have a merge of 2 empty repo parents where the result is the complete source of the latest version of Kubernetes!

discuss

order

Groxx|1 year ago

Yep. Stuff like this is part of why I'm a rebaser.

Rebase is simple. Always. The end result is obvious and clear and can only be interpreted in one way.

Merge has lots of little sharp edges and surprises if you don't know every single tiniest detail.

Almost nobody knows it in that level of detail, so it's a terrible choice for interacting with anyone else. If you're on your own, sure, do whatever - many things are not built solo though.

noirscape|1 year ago

My personal preference is merge but using the --no-ff flag. That way you get all the advantages of a rebase (since all your original commits are rebased into the target branch) but you also get a merge commit to confirm that all those changes were a part of the same set of patches.

That can often help a lot to figure out why something ended up the way it did, but you also don't turn your entire history into a flat pile of disparate commits.

zilti|1 year ago

"But it is littering the commit history with useless commits!" is what I always hear

btilly|1 year ago

One idiot with rebase destroys history with no trace. I worked with such an idiot in a parallel team. I can't say how many weeks of work randomly got destroyed by said idiot.

I hate rebase on shared code I don't care how clean jt looks. Don't mess with history.

doix|1 year ago

I really don't understand how you can lose weeks of work. The person that would have done the force push would have the original commit in their reflog. ORIG_HEAD would be set.

Everyone else that had a copy of the repo would have had a copy of the "lost" commits.

I really cannot imagine how many things would have to go wrong for weeks of work to be lost.

arghwhat|1 year ago

One never rebases shared code. They rebase their own work branch. Messing with history of master/main/integration branches should be blocked.

Rebase is a necessary part of a workflow even if you like merge commits. You're severely missing out if interactive rebases are not part of your toolbox.

Feathercrown|1 year ago

I wouldn't consider rebasing your own local commits on top of a more recent remote master to be messing with history in any meaningful way, and that's the most useful method of rebasing.

globular-toast|1 year ago

Rebase cannot destroy "weeks of work". No git command can delete commits. Unless you have some insane garbage collection policy that is very far from any defaults. This is your fault for not understanding your tools.

ansible|1 year ago

Didn't you guys have filesystem backups of a shared git repository?

This is exactly what backups are for.

nvy|1 year ago

I believe that the semantics of < > vs "" is actually compiler-dependent but on every compiler that matters, #including with angle brackets is the semantic for "the system header" whereas using quotes gives preference to files in your local source tree.

So for example if you #include <foo> then the compiler (actually the preprocessor, but whatever) looks in the system's standard location, whereas if you #include "foo" then it looks in the local tree.

ephimetheus|1 year ago

I think that’s just the ordering though. “” will also end up searching the system paths, it will just check the local paths first.

ripe|1 year ago

You are right; a good explanation of the rules is in the C FAQ [1], which points to a newsgroup posting by Kaz Kylehu [2].

I am posting the summary here, although please do read the original if you have time:

The most portable thing to do is to use "" for including files within your project, and to use <> only for implementation supplied files.

(Disclosure: I was one of the contributors to the C FAQ).

[1] https://c-faq.com/cpp/inclkinds.html

[2] https://c-faq.com/cpp/inclk.kaz.html

prerok|1 year ago

What I find strange is that <> traditionally included system header files and "" included local files. They used different include paths, so you could have a header file in your sources with the same name as the system header file and then could control whether you are including one or the other based on using <> or "".

Anyway, I thought the distinction was lost in later compilers in favor of a single include path and then just taking the first file found when looking at potential matches through include path.

It seems the author of that merge thought the same thing. So, the distinction is actually still used by compilers?

pavon|1 year ago

With both GCC and Visual C++, the “” form first searches local paths and then system paths, while the <> form only searches system paths. Guess some BSDs are stricter about local paths.

Gibbon1|1 year ago

> But the fact that a merge can have arbitrary changes in it always bothers me!

After that xy thing where they were trying to install a back door having changes that are hidden like this is a big red flag.

In fact changing include <something.h> to include "something.h" with a hidden commit like this isn't a red flag it's a big rotating alarm with a siren. Someones trying set things up to include malicious code via a faked system lib.

saagarjha|1 year ago

Sadly, not all of us can live in the tech equivalent of Bond films. There is only so many xz backdoors to go around.

arghwhat|1 year ago

All but the first commit has parents. All commits point to the state of the file tree at that point.

A "merge commit" is nothing more than a commit claiming any number of parents greater than one. It is still its own file tree reference that decides how the tree looks, and nothing dictates that it should be related to the parents.

tsimionescu|1 year ago

If that were true, then git log -p would have worked. The reality is that merge commits are treated differently from other commits by many parts of git. Saying that they are "just a commit with multiple parents" gives people the wrong impression.

Git is more than the data structure backing it. And many parts of git make all sorts of assumptions that treat things that are more or less identical in the data model as actually being different. Tags are not the same thing as branches, for example, even though they are stored in virtually the same way.

kccqzy|1 year ago

You are right that conceptually this is okay. But it is a UI problem that commands the author tried didn't manage to show the difference between the merge commit against any of its parents.

devjab|1 year ago

Wouldn’t you have the same amount of merge conflicts with rebase? Especially if you don’t do it often, which you frankly also should with merge?

I have to admit that I never really understood the advantages of rebase, and what I mean by this is they I actually don’t understand how the dangers of rebase out-weighs any form of advantages. Especially because on of the major advantages of merge is that you can squash your local commit history when you submit it to your main branch.

What we do is that we tie every pull request to a relatively small feature task, and because we do this, we genuinely don’t care about the individual commits developers do. Which means they can commit really silly messages if they are heading to a meeting or if they are just tired at the end of the day. It also helps with them merging main into their branch often, because it doesn’t taint the history.

The biggest advantage we’ve seen, that maybe we didn’t expect, is that nobody ever fucks up our tree in a way that needs someone who actually understands git to solve. We’ve also locked down the use of force push so that is not available to anyone unless it’s absolutely needed. Part of the reason I set this up initially was to protect myself from me, but it’s been a good thing since.

But I’m actually curious if it’s wrong.

doix|1 year ago

> Especially because on of the major advantages of merge is that you can squash your local commit history when you submit it to your main branch.

Squashing is in no-way limited to merging and is actually done by doing an interactive rebase. Nothing is stopping you from squashing without creating a merge commit. It's entirely separate.

If you're squashing everything anyway, what does merging even give you? Is your main branch just:

* merge B

* squashed commit B

* merge A

* squashed commit A

If you didn't merge, you'd have:

* squashed commit B

* squashed commit A

> What we do is that we tie every pull request to a relatively small feature task, and because we do this, we genuinely don’t care about the individual commits developers do.

Except eventually there is a large feature task and then you end up with a giant commit that is annoying when git-bisecting.

But at the end of the day, these things only matter if you are spelunking through git history and/or using things like git bisect. If your git history is "write-only & rollback", then none of this stuff matters.

xorcist|1 year ago

> advantages of merge is that you can squash your local commit history

No, it's the other way around. Squashing is a type of rebase.

Most workflows involve both. Merges can also be fast-forward merges, which are indistinguishable from rebases. Choosing between a rebase and a merge operation is often the wrong question to ask. The question is what state you wish the repository to end up in.

> I’m actually curious if it’s wrong

Look at "git log". It is readable and easy to understand? It is obvious why each commit was made, and why alternative solutions were turned down?

Are you able to use "git bisect" to track down problems?

Then you're doing it right. If not, think about what a functional commit log would look like and how you would get there. Working together is culture, and what type of merges you decide to use is just a tiny part of that culture.

paulddraper|1 year ago

But a rebased commit can also have arbitrary changes!

---

P.S. Any commit can have any change. Or no change.

A "commit" is a version...a message, a tree, some metadata, and 0 or more parents. In fact it's not even a change/diff/patchset per se. Though will often compare it against its assigned parents. If it has multiple parents, you'd have to choose which to compare. If it has zero parents, you can't compare against any parents.

ptsneves|1 year ago

Yes, except git log will show all the commits that got into the branch, while with merge you need git log -m otherwise there are invisible commits(and diffs) in a pretty common workflow. I don’t know why this is the default behaviour.

Git log only shows one tree not parallel trees from the merge.

red_admiral|1 year ago

The <> version searches the library path (usually /usr/include/* but can be modified with flags) whereas the "" searches the current working directory.

thaumasiotes|1 year ago

> I wont claim to understand C and the reason why <> is better than “”. I assume it is.

That one's obvious, you can type <> and you can't type “”.